package com.example.teesystem.controller;

import cn.hutool.core.lang.id.NanoId;
import com.example.teesystem.common.exception.Assert;
import com.example.teesystem.common.utils.ResultCode;
import com.example.teesystem.common.websocket.model.*;
import com.example.teesystem.entity.Issue;
import com.example.teesystem.entityDto.IssueBriefMessage;
import com.example.teesystem.mapper.IssueMapper;
import com.example.teesystem.service.PKService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Data
@Controller
@RequiredArgsConstructor
public class PKController {
//    @Value("${tee.pk.destination}")
//    private String DESTINATION;
//    @Value("${tee.pk.issue-size}")
//    private Integer ISSUE_SIZE;
//
//    private final SimpMessagingTemplate simpMessagingTemplate;
//    private final IssueMapper issueMapper;
    private final PKService pkService;
    
    // 当有新的连接加入时，存储该连接， key 为 sessionId，value 为 uid
    public static final Map<String, Integer> sessions = new ConcurrentHashMap<>();
    // 存储用户信息，用 Map 存储，key 为 userId，value 为玩家队列
    public static final Map<Integer, UserInfo> userInfos = new ConcurrentHashMap<>();
    // 存储分组信息，key 为 groupId，value为 group 信息
    public static final Map<String, GroupInfo> groupInfos = new ConcurrentHashMap<>();
    
    @MessageMapping("/pk.pk")
    public void pk(@Payload(required = false) PKMessage pkMessage) {
        // 1. 判断是否重复提交匹配和校验是否传递需要的参数
        Assert.notNull(ResultCode.PARAMETER_MISS, pkMessage.getUid(), pkMessage.getCourseId(), pkMessage.getMessageType());
        
        if(MessageType.START_MATCHING.equals(pkMessage.getMessageType())) {
            
            System.out.println("用户" + pkMessage.getUid() + "开始匹配");
            
            pkService.startMatch(pkMessage);
            
            //PKController.printStatus();
        } else if(MessageType.QUIT_MATCHING.equals(pkMessage.getMessageType())) {
    
            System.out.println("用户" + pkMessage.getUid() + "取消匹配");
    
            pkService.quitMatch(pkMessage);
    
            //PKController.printStatus();
        } else if(MessageType.ANSWER.equals(pkMessage.getMessageType())) {
    
            System.out.println("用户" + pkMessage.getUid() + "正在答题");
    
            pkService.answer(pkMessage);
    
            //PKController.printStatus();
        }
        else if(MessageType.END.equals(pkMessage.getMessageType())) {

            System.out.println("用户" + pkMessage.getUid() + "释放链接");
            if(pkMessage.getGroupId()!=null) {
                pkService.end(pkMessage.getGroupId());
            }else {
                pkService.quitMatch(pkMessage);
            }
            //PKController.printStatus();
        }
    }
    
    public static void printStatus() {
        System.out.println("------- 现有连接 --------");
        sessions.values().stream().forEach(System.out::println);
        System.out.println("---------------" + '\n');
        System.out.println("------- 现有用户 --------");
        userInfos.values().stream().forEach(System.out::println);
        System.out.println("---------------" + '\n');
        System.out.println("------- 现有分组 --------");
        for(GroupInfo groupInfo : groupInfos.values()) {
            System.out.println("groupId: " + groupInfo.getId());
            System.out.println("userA: " + groupInfo.getUserA());
            System.out.println("userB: " + groupInfo.getUserB());
            System.out.println("正在回答的题目： " + groupInfo.getCurIssue());
            System.out.println("题目列表：");
            groupInfo.getIssues().forEach(System.out::println);
            System.out.println("答题情况：");
            groupInfo.getAnswerConditions().entrySet().forEach(System.out::println);
            System.out.println('\n');
        }
        System.out.println("---------------" + '\n');
    }
    
//    /**
//     * 1. 判断玩家是否重复提交匹配请求
//     * 2. 将玩家放入到匹配队列中
//     * 3. 如果匹配成功，需要建立一个分组，并抽题
//     * @param pkMessage
//     */
//    private synchronized void startMatch(PKMessage pkMessage) {
//        // 1. 判断玩家是否重复提交匹配请求
//        UserInfo userInfo = userInfos.get(pkMessage.getUid());
//        if(userInfo != null) {
//            simpMessagingTemplate.convertAndSendToUser(pkMessage.getUid().toString(), DESTINATION, "正在匹配中，请勿重复提交");
//            return;
//        }
//
//        // 2. 添加到匹配队列中
//        UserInfo newUser = new UserInfo(pkMessage.getUid(), pkMessage.getCourseId(), UserType.MATCHING);
//        userInfos.put(newUser.getUid(), newUser);
//
//        System.out.println("新用户加入到匹配队列：" + newUser);
//        System.out.println("------- 现有用户 --------");
//        userInfos.values().stream().forEach(System.out::println);
//        System.out.println("---------------");
//
//        // 3. 检查队列中是否有大于等于两个玩家正在匹配，若存在，则创建分组
//        List<UserInfo> matchingUsers = this.findMatchingUsers(pkMessage.getCourseId());
//        if(matchingUsers.size() == 2) {
//            // 获取正在匹配的用户
//            UserInfo userA = matchingUsers.get(0);
//            UserInfo userB = matchingUsers.get(1);
//
//            // 更新用户状态
//            userA.setType(UserType.PLAYING);
//            userA.setUpdateTime(LocalDateTime.now());
//            userB.setType(UserType.PLAYING);
//            userB.setUpdateTime(LocalDateTime.now());
//
//            // 创建分组
//            GroupInfo groupInfo = new GroupInfo(NanoId.randomNanoId(), userA, userB, this.getIssues(pkMessage.getCourseId()));
//            groupInfos.put(groupInfo.getId(), groupInfo);
//
//            System.out.println("新建一对分组：" + groupInfo);
//            System.out.println("------- 现有分组 --------");
//            groupInfos.values().stream().forEach(System.out::println);
//            System.out.println("---------------");
//
//            // 将分组信息发送给用户
//            GroupResult result = new GroupResult(groupInfo.getId(), userA.getUid(), userB.getUid(), groupInfo.getIssues().size());
//            simpMessagingTemplate.convertAndSendToUser(userA.getUid().toString(), DESTINATION, result);
//            simpMessagingTemplate.convertAndSendToUser(userB.getUid().toString(), DESTINATION, result);
//        }
//    }
//
//    /**
//     * 1. 从匹配队列中移除玩家
//     * @param pkMessage
//     */
//    private synchronized void quitMatch(PKMessage pkMessage) {
//        // 从匹配队列中寻找该玩家
//        UserInfo userInfo = userInfos.get(pkMessage.getUid());
//        // 如果玩家存在且状态为正在匹配则移除
//        if(userInfo != null && UserType.MATCHING.equals(userInfo.getType())) {
//            userInfos.remove(userInfo.getUid());
//            simpMessagingTemplate.convertAndSendToUser(userInfo.getUid().toString(), DESTINATION, "取消匹配成功");
//        }
//
//        System.out.println("------- 现有用户 --------");
//        userInfos.values().stream().forEach(System.out::println);
//        System.out.println("---------------");
//    }
//
//    /**
//     * 寻找正在匹配的玩家
//     * @param courseId 课程 id
//     * @return 正在匹配的玩家
//     */
//    private List<UserInfo> findMatchingUsers(Integer courseId) {
//        return userInfos.values().stream()
//                .filter(userInfo -> courseId.equals(userInfo.getCourseId()) && UserType.MATCHING.equals(userInfo.getType()))
//                .limit(2)
//                .collect(Collectors.toList());
//    }
//
//    /**
//     * 随机抽题
//     * @param courseId 课程 id
//     * @return 该课程下的随机题列表
//     */
//    private List<Issue> getIssues(Integer courseId) {
//        return issueMapper.getPkIssues(courseId, ISSUE_SIZE);
//    }
//
//    /**
//     * 1. 从分组中统计答题情况
//     * @param pkMessage
//     */
//    private void end(PKMessage pkMessage) {
//        GroupInfo groupInfo = groupInfos.get(pkMessage.getGroupId());
//        List<Issue> pkIssueList = groupInfo.getIssues();
//
//        List<PKResultMessage> userAResult = new ArrayList<>();
//        List<PKResultMessage> userBResult = new ArrayList<>();
//
//        // 统计答题情况
//        for (Issue issue : pkIssueList){
//            if (groupInfo.getAnswerConditions().get(issue.getId()) == null){
//                userAResult.add(new PKResultMessage(issue, false));
//                userBResult.add(new PKResultMessage(issue, false));
//            }else if (groupInfo.getAnswerConditions().get(issue.getId()).equals(groupInfo.getUserA().getUid())){
//                userAResult.add(new PKResultMessage(issue, true));
//                userBResult.add(new PKResultMessage(issue, false));
//            }else {
//                userAResult.add(new PKResultMessage(issue, false));
//                userBResult.add(new PKResultMessage(issue, true));
//            }
//        }
//
//        // 将结果返回给用户
//        simpMessagingTemplate.convertAndSendToUser(groupInfo.getUserA().getUid().toString(), DESTINATION, userAResult);
//        simpMessagingTemplate.convertAndSendToUser(groupInfo.getUserB().getUid().toString(), DESTINATION, userBResult);
//    }
//
//    /**
//     * 1. 验证题目是否正确
//     * 2. 若正确，则更新分组信息，并将下一道题传给两个玩家
//     * 3. 错误则返回答题错误信息
//     * @param pkMessage
//     */
//    private synchronized void answer(PKMessage pkMessage) {
//        // 校验传入参数
//        Assert.notNull(ResultCode.PARAMETER_MISS, pkMessage.getGroupId(), pkMessage.getCurIssue(), pkMessage.getAnswer());
//
//        GroupInfo groupInfo = groupInfos.get(pkMessage.getGroupId());
//        if (groupInfo.getCurIssue() == null){
//            groupInfo.setCurIssue(0);
//        }
//        // 添加校验
//        if (pkMessage.getCurIssue().equals(groupInfo.getCurIssue())) {
//            if (validAnswer(pkMessage)) {
//                //更新分组信息
//                groupInfo.setUpdateTime(LocalDateTime.now());
//
//                Map<Integer, Integer> answerConditions = groupInfo.getAnswerConditions();
//                answerConditions.put(pkMessage.getCurIssue(), pkMessage.getUid());
//                groupInfo.setAnswerConditions(answerConditions);
//
//                int nextIssue = pkMessage.getCurIssue() + 1;
//                groupInfo.setCurIssue(nextIssue);
//
//                if (nextIssue == groupInfo.getIssues().size()) {
//                    end(pkMessage);
//                } else {
//                    // 发送下一道题给玩家
//                    IssueBriefMessage result = new IssueBriefMessage(groupInfo.getIssues().get(nextIssue));
//                    simpMessagingTemplate.convertAndSendToUser(groupInfo.getUserA().getUid().toString(), DESTINATION, result);
//                    simpMessagingTemplate.convertAndSendToUser(groupInfo.getUserB().getUid().toString(), DESTINATION, result);
//                }
//            } else {
//                Integer curIssue = pkMessage.getCurIssue();
//
////            PkIssueMessage answersResult = new PkIssueMessage(groupInfo.getIssues().get(curIssue), StringUtils.join(pkMessage.getAnswer(), '$'));
//                PkIssueMessage answersResult = new PkIssueMessage(groupInfo.getIssues().get(curIssue), pkMessage.getAnswer());
//                PkIssueMessage result = new PkIssueMessage(groupInfo.getIssues().get(curIssue), "");
//
//                if (pkMessage.getUid().equals(groupInfo.getUserA().getUid())) {
//                    simpMessagingTemplate.convertAndSendToUser(groupInfo.getUserA().getUid().toString(), DESTINATION, answersResult);
//                    simpMessagingTemplate.convertAndSendToUser(groupInfo.getUserB().getUid().toString(), DESTINATION, result);
//                } else {
//                    simpMessagingTemplate.convertAndSendToUser(groupInfo.getUserA().getUid().toString(), DESTINATION, result);
//                    simpMessagingTemplate.convertAndSendToUser(groupInfo.getUserB().getUid().toString(), DESTINATION, answersResult);
//                }
//            }
//        }
//    }
//
//
//    /**
//     * 判断玩家答案是否正确
//     * @param pkMessage
//     * @return
//     */
//    private Boolean validAnswer(PKMessage pkMessage) {
//        Issue issue = groupInfos.get(pkMessage.getGroupId()).getIssues().get(pkMessage.getCurIssue());
////        String answer = StringUtils.join(pkMessage.getAnswer(), '$');
//        String answer = pkMessage.getAnswer();
//
//        String[] realAnswers = issue.getAnswer().toUpperCase().split("\\$");
//        String[] studentAnswers = answer.toUpperCase().split("\\$");
//
//        if (realAnswers.length != studentAnswers.length){
//            return false;
//        }else {
//            List<String> rightAnswer = Arrays.asList(realAnswers);
//            boolean judge = true;
//            for (String s:studentAnswers){
//                if(!rightAnswer.contains(s)){
//                    judge = false;
//                    break;
//                }
//            }
//            return judge;
//        }
//    }
//
//    /**
//     * 1. 定时（1min）检查所有分组
//     * 2. 若某分组更新时间在一分钟前，则判断为双方掉线，移除分组信息和用户信息
//     */
//    @Scheduled(fixedDelay = 60 * 1000)
//    private void checkConnection() {
//        LocalDateTime curDate = LocalDateTime.now();
//        List<String> removeKeys = new ArrayList<>();
//
//        for (String key : groupInfos.keySet()){
//            Duration duration = Duration.between(groupInfos.get(key).getUpdateTime(), curDate);
//            if (duration.toMinutes() > 1){
//                removeKeys.add(key);
//
//                //移除用户信息
//                userInfos.remove(groupInfos.get(key).getUserA().getUid());
//                userInfos.remove(groupInfos.get(key).getUserB().getUid());
//            }
//        }
//
//        //移除分组信息
//        for (String key : removeKeys) {
//            groupInfos.remove(key);
//        }
//    }
}
